package thread;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class BounceThread {
	public static void main(String[] agrs) {
		JFrame f = new BounceFrame();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setVisible(true);
	}
}

class BallRunnable implements Runnable {
	public BallRunnable(Ball ball, Component component) {
		this.ball = ball;
		this.component = component;
	}
	
	private Ball ball;
	private Component component;
	private static final int STEP = 10000;
	private static final int DELAY = 5;
	
	public void run() {
		try {
			for(int i=1; i<STEP; i++) {
				ball.move(component.getBounds());
//				component.repaint();
				Thread.sleep(DELAY);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class Refresh extends Thread {
	private Component component;
	private static final int DELAY = 3;
	
	public Refresh(Component c) {
		component = c;
	}
	
	public void run() {
		try {
			while(true) {
				component.repaint();
				this.sleep(DELAY);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class Ball {
	private static int XSIZE = 15;
	private static int YSIZE = 15;
	private double x = 0;
	private double y = 0;
	private double dx = 1;
	private double dy = 1;
	
	public void move(Rectangle2D bound) {
		x += dx;
		y += dy;
		
		if(x < bound.getMinX()) {
			x = bound.getMinX();
			dx = -dx;
		}
		if(x + XSIZE >= bound.getMaxX()) {
			x = bound.getMaxX() - XSIZE;
			dx = -dx;
		}
		if(y < bound.getMinY()) {
			y = bound.getMinY();
			dy = -dy;
		}
		if(y + YSIZE >= bound.getMaxY()) {
			y = bound.getMaxY() - YSIZE;
			dy = -dy;
		}
	}
	
	public Ellipse2D getShape() {
		return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
	}
	
}

class BallPanel extends JPanel {
	private ArrayList<Ball> balls = new ArrayList<Ball>();
	
	public void addBall(Ball ball){
		balls.add(ball);
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		for(Ball ball: balls) {
			g2.fill(ball.getShape());
		}
	}
}

class BounceFrame extends JFrame {
	private BallPanel panel;
	private ArrayList<Thread> threads = new ArrayList<Thread>();
	private static final int DEFAULT_WIDTH = 450;
	private static final int DEFAULT_HEIGHT = 350;
	private static final int STEP = 1000;
	private static final int DELAY = 3;
	
	public BounceFrame() {
		super.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
		super.setTitle("Bource Thread");
		
		panel = new BallPanel();
		super.add(panel, BorderLayout.CENTER);
		JPanel buttonPanel = new JPanel();
		this.addButton(buttonPanel, "Start", new ActionListener(){
			public void actionPerformed(ActionEvent event) {
				addBall();
			}
		});
		this.addButton(buttonPanel, "Exit", new ActionListener(){
			public void actionPerformed(ActionEvent event) {
				System.exit(0);
			}
		});
		this.addButton(buttonPanel, "Stop", new ActionListener(){
			public void actionPerformed(ActionEvent event) {
				JButton jb = (JButton)event.getSource();
				if("Stop".equals(jb.getText())) {
					for(Thread t : threads) {
						t.interrupt();
					}
					jb.setText("Restart");
				}else {
					for(Thread t : threads) {
						System.out.println(t.getState());
						System.out.println(t.isInterrupted());
						t.interrupted();
						System.out.println(t.isInterrupted());
						System.out.println(t.getState());
						t.start();
					}
					jb.setText("Stop");
				}
			}
		});
		super.add(buttonPanel, BorderLayout.SOUTH);
		Thread t = new Refresh(panel);
		t.start();
	}
	
	private void addButton(Container c, String title, ActionListener l) {
		JButton jb = new JButton(title);
		jb.addActionListener(l);
		c.add(jb);
	}
	
	public void addBall() {
		Ball b = new Ball();
		panel.addBall(b);
		BallRunnable r = new BallRunnable(b, panel);
		Thread t = new Thread(r);
		threads.add(t);
		t.start();
	}
}
